/*-----------------------------------------------------------------------------
	The contents of this file are subject to the Mozilla Public License
	Version 1.1 (the "License"); you may not use this file except in
	compliance with the License.You may obtain a copy of the License at
	http://www.mozilla.org/MPL/MPL-1.1.html
	
	Software distributed under the License is distributed on an "AS IS"
	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	License for the specific language governing rights and limitations
	under the License.
	
	The Original Code is Fever Framework code.
	
	The Initial Developer of the Original Code is Romain Ecarnot.
	Portions created by Initial Developer are Copyright (C) 2006
	the Initial Developer. All Rights Reserved.
	
	Contributor(s):
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
-----------------------------------------------------------------------------*/

import org.aswing.border.EmptyBorder;
import org.aswing.BorderLayout;
import org.aswing.Container;
import org.aswing.Insets;
import org.aswing.JButton;
import org.aswing.JFrame;
import org.aswing.JList;
import org.aswing.JPanel;
import org.aswing.JScrollPane;

import com.bourre.data.collections.Map;
import com.bourre.log.LogChannel;
import com.bourre.log.LogEvent;
import com.bourre.log.Logger;
import com.bourre.log.LogLevel;
import com.bourre.log.LogListener;

import fever.display.FeverStage;

import fvaswing.utils.tracer.FvTracerCellFactory;
import fvaswing.utils.tracer.FvTracerMessage;

/**
 * Displays log messages from <strong>Pixlib</strong> Logging API.
 * 
 * <p>Implements <strong>Pixlib LogListener</strong> interface
 * 
 * <p>Example
 * {@code
 *   Logger.getInstance().addLogListener( FvAsWingTracer.getInstance(), FeverDebug.channel );
 *   
 *   FeverDebug.WARN( 'A warning message' );
 * }
 * 
 * @author Romain Ecarnot
 */
class fvaswing.utils.tracer.FvAsWingTracer implements LogListener
{
	//-------------------------------------------------------------------------
	// Private properties
	//-------------------------------------------------------------------------
	
	private static var _instance : FvAsWingTracer;
	
	private var _mColor : Map;
	private var _model : Array;
	
	private var _containerPanel : JPanel;
	private var _scrollPane : JScrollPane;
	private var _clearButton : JButton;	private var _logView : JFrame;
	private var _list : JList;
	
	
	//-------------------------------------------------------------------------
	// Public API
	//-------------------------------------------------------------------------
	
	/**
	 * Creates {@link FvAsWingTracer} instance and connects it to passed 
	 * {@code channel} for logging API.
	 * 
	 * <p>Example
	 * {@code 
	 *   FvAsWingTracer.connect( FeverDebug.channel ).open();
	 * }
	 */
	public static function connect( channel : LogChannel ) : FvAsWingTracer
	{
		var o : FvAsWingTracer = FvAsWingTracer.getInstance();
		Logger.getInstance().addLogListener( o, channel );
		return o;	
	}
	
	/**
	 * Creates and returns a <strong>FvAsWingTracer</strong> instance.
	 */
	public static function getInstance() : FvAsWingTracer
	{
		if( _instance == undefined ) _instance = new FvAsWingTracer();
		return _instance;
	}
	
	/**
	 * Sends log message obtained from the passed-in {@code e} model to all
	 * registred {@code Logger} listeners.
	 *
	 * @param e Pixlib LogEvent instance
	 */
	public function onLog( e : LogEvent ) : Void
	{
		_model.push( 
			new FvTracerMessage( 
				buildLogMessage( e ), 
				_mColor.get( e.level ) 
			) 
		);
		_refreshList();
	}
	
	/**
	 * Builds custom log message.
	 * 
	 * <p>Overrides this method to customize your message ouput.
	 * 
	 * @return String
	 */
	public function buildLogMessage( e : LogEvent ) : String
	{
		return String( e.content );	
	}
	
	/**
	 * Opens tracer in dialog mode.
	 */
	public function open() : Void
	{
		_logView.show();	
	}
	
	/**
	 * Returns only logging container ( not frame ).
	 */
	public function getContainer() : Container
	{
		if( _logView.isShowing() ) _logView.tryToClose();
		
		_containerPanel.setPreferredHeight( 100 );
		return _containerPanel;	
	}
	
	
	//-------------------------------------------------------------------------
	// Private implementation
	//-------------------------------------------------------------------------
	
	/**
	 * Constructor.
	 */
	private function FvAsWingTracer()
	{
		_initColorMap();
		_handleClearLog();
		
		_logView = _createDialog();
	}
	
	/**
	 * Creates JFrame and subcomponents for messages UI.
	 */
	private function _createDialog() :JFrame
	{
		var frame : JFrame = new JFrame( FeverStage.getInstance().getLoggerTarget(), 'AsWing tracer', false );
		frame.setResizable( true );
		frame.setClosable( false );
		
		_scrollPane = new JScrollPane( _getListComponent() );
		_clearButton = new JButton( 'clear' );
		_clearButton.addActionListener( _handleClearLog, this );
		
		_containerPanel = new JPanel( new BorderLayout( 5, 5 ) );
		_containerPanel.setBorder( new EmptyBorder( null, new Insets( 5, 5, 5, 5 ) ) );
		
		_containerPanel.append( _scrollPane, BorderLayout.CENTER );		_containerPanel.append( _clearButton, BorderLayout.SOUTH );
		frame.setContentPane( _containerPanel );
		 
		frame.pack();
		return frame;
	}
	
	/**
	 * Creates JList
	 */
	private function _getListComponent() : JList
	{
		_list = new JList( null, new FvTracerCellFactory( ) );
		_list.setSelectionMode( JList.SINGLE_SELECTION );
		_list.setPreferredSize( 200, 75 );
		_list.setOpaque( true );
		return _list;
	}
	
	/**
	 * Refresh JList
	 */
	private function _refreshList() : Void
	{
		_list.setListData( _model );
		
		_list.ensureIndexIsVisible( _list.getLastVisibleIndex() );
	}
	
	/**
	 * Clears JList
	 */
	private function _handleClearLog() : Void
	{
		_model = new Array();
		_refreshList();
	}
	
	/**
	 * Inits color map collection used to {@code LogLevel} state.
	 */
	private function _initColorMap() : Map
	{
		_mColor = new Map();
		_mColor.put( LogLevel.DEBUG, 0x1394D6 );
		_mColor.put( LogLevel.INFO, 0x12C9AC );
		_mColor.put( LogLevel.WARN, 0xFFCC00 );
		_mColor.put( LogLevel.ERROR, 0xFF6600 );
		_mColor.put( LogLevel.FATAL, 0xFF0000 );
		return _mColor;
	}	

}